package org.istt.dao.hibernate;

import java.sql.SQLException;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Example;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.istt.dao.AttachFileDao;
import org.istt.domain.AttachFile;
import org.istt.domain.AttachFileDetail;
import org.istt.domain.Category;
import org.istt.domain.CategoryType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.ObjectRetrievalFailureException;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.stereotype.Repository;

/**
 * This class interacts with Spring and Hibernate to save and retrieve
 * AttachFile objects.
 * 
 * @author NDTHO
 */
@Repository(value = "attachFileDao")
public class AttachFileDaoHibernate extends BaseDaoHibernate<AttachFile, Long>
		implements AttachFileDao {
	Log logger = LogFactory.getLog(AttachFileDaoHibernate.class);

	@Autowired
	public AttachFileDaoHibernate(SessionFactory sessionFactory) {
		super(sessionFactory);
	}

	public List<AttachFile> getAttachFiles() {
		return findAll();
	}

	public AttachFile getAttachFile(Long id) {
		AttachFile attachFile = findById(id, false);
		if (attachFile == null) {
			throw new ObjectRetrievalFailureException(AttachFile.class, id);
		}
		return attachFile;
	}

	public void saveAttachFile(AttachFile attachFile) {
		makePersistent(attachFile);

		if (logger.isDebugEnabled()) {
			logger.debug("attachFileId set to: " + attachFile.getId());
		}
	}

	public void removeAttachFile(Long id) {
		makeTransient(getAttachFile(id));
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<AttachFile> searchAttachFile(final String attachFileName,
			final Category category, final CategoryType categoryType) {
		
		return (List<AttachFile>) hibernateTemplate
				.execute(new HibernateCallback() {
					@Override
					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {
						Criteria criteria = session
								.createCriteria(AttachFile.class);
						if (attachFileName != null
								&& !"".equals(attachFileName))
							criteria.add(Restrictions.ilike("attachFileName",
									"%" + attachFileName + "%"));
						if (category != null)
							criteria.add(Restrictions.eq("category", category));
						if (categoryType.getId() != 0l)
							criteria.add(Restrictions.eq("categoryType", categoryType));
						return criteria.list();
					}
				});
	}
	
	
	/*
	 * (non-Javadoc)
	 * 
	 * @see org.istt.dao.AttachFileDao#findByCateId(java.lang.Long)
	 */
	@SuppressWarnings("unchecked")
	@Override
	public List<AttachFile> findByCateId(final Long cateId) {
		return (List<AttachFile>) hibernateTemplate
				.execute(new HibernateCallback() {

					@Override
					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {
						return session.createCriteria(getPersistentClass())
								.createCriteria("category")
								//.addOrder(Order.asc("position"))
								.add(Restrictions.idEq(cateId)).list();
					}
				});
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<AttachFile> findByCatIdAndCatTypeId(Long categoryId,
			Long categoryTypeId) {
		String hsql = "from AttachFile af where af.category.id = ? and af.categoryType.id = ? order by af.position asc";
		return hibernateTemplate.find(hsql, new Long[]{categoryId, categoryTypeId});
	}

	   /*
	    * (non-Javadoc)
	    * @see org.istt.dao.Dao#isUnique(java.lang.String[], java.lang.String[], java.io.Serializable)
	    */
	@SuppressWarnings("unchecked")
	@Override
	   public boolean isUnique(final String[] fields, final String[] value, final Long id, final Long cateId, final Long cateTypeId, final Long docTypeId) {
		   return (Boolean) hibernateTemplate.execute(new HibernateCallback() {
				
				@Override
				public Object doInHibernate(Session session) throws HibernateException,
						SQLException {
					Criteria crit = session.createCriteria(getPersistentClass());
					crit.createCriteria("category").add(Restrictions.idEq(cateId));
					crit.createCriteria("categoryType").add(Restrictions.idEq(cateTypeId));
					crit.createCriteria("documentType").add(Restrictions.idEq(docTypeId));
					
					if (id != null) {
						crit.add(Restrictions.not(Restrictions.idEq(id)));
					   }
					   
					   for (int i = 0; i < fields.length; i++) {
						   crit.add(Restrictions.ilike(fields[i], value[i], MatchMode.EXACT));
					   }
			        return ((Long)crit.setProjection(Projections.rowCount()).uniqueResult()) == 0l;
				}
			});
	   };	
	
	   
	   public int countFileUseAttach(final Long attachFileId) {
			return (Integer) hibernateTemplate.execute(new HibernateCallback<Object>() {

				@Override
				public Object doInHibernate(Session session)
						throws HibernateException, SQLException {
					
					Criteria criteria = session.createCriteria(AttachFileDetail.class)
							.add(Example.create(new AttachFileDetail()))
							.createCriteria("attachFile")
							.add(Restrictions.idEq(attachFileId))
							.setProjection(Projections.rowCount());
					return ((Long)criteria.uniqueResult()).intValue();
				}
			});
		}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	@Override
	public List<AttachFile> findAttachFile(final Long categoryId,final Long cagegoryTypeId) {
		return (List<AttachFile>) hibernateTemplate.execute(new HibernateCallback() {

			@Override
			public Object doInHibernate(Session session) throws HibernateException, SQLException {
				
				Criteria crit = session.createCriteria(getPersistentClass());
				crit.createCriteria("category").add(Restrictions.idEq(categoryId));
				crit.createCriteria("categoryType").add(Restrictions.idEq(cagegoryTypeId));
				crit.addOrder(Order.asc("position"));
				
				return crit.list();
			}
		});
	}
	
	@Override
	public int getRecordCount(final Long categoryId, final Long categoryTypeId, final Long documentTypeId){
		return (Integer)hibernateTemplate.execute(new HibernateCallback<Object>() {

			@Override
			public Object doInHibernate(Session session)
					throws HibernateException, SQLException {
				// TODO Auto-generated method stub
				
				Criteria criteria = session.createCriteria(getPersistentClass());
				criteria.createCriteria("category").add(Restrictions.idEq(categoryId));
				criteria.createCriteria("categoryType").add(Restrictions.idEq(categoryTypeId));
				criteria.createCriteria("documentType").add(Restrictions.idEq(documentTypeId));
				criteria.setProjection(Projections.rowCount());
				return ((Long)criteria.uniqueResult()).intValue();
			}
			
		});
	}
}
